package com.example.yx.demo25;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.annotation.ExpressionValueMethodArgumentResolver;
import org.springframework.web.method.annotation.ModelFactory;
import org.springframework.web.method.annotation.RequestHeaderMethodArgumentResolver;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.*;
import com.example.yx.demo25.WebConfig;

import java.lang.reflect.Method;

public class A25 {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);

        //创建一个处理器
        RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
        handlerAdapter.setApplicationContext(context);
        handlerAdapter.afterPropertiesSet();




        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setParameter("name","张三");

        ServletInvocableHandlerMethod handlerMethod =
                new ServletInvocableHandlerMethod
                        (new WebConfig.Controller1(), WebConfig.Controller1.class.getMethod("foo", WebConfig.User.class));

        ServletRequestDataBinderFactory binderFactory = new ServletRequestDataBinderFactory(null,null);

        handlerMethod.setDataBinderFactory(binderFactory);
        handlerMethod.setParameterNameDiscoverer(new DefaultParameterNameDiscoverer());
        handlerMethod.setHandlerMethodArgumentResolvers(getThese(context));

        ModelAndViewContainer container = new ModelAndViewContainer();
        //创建一个ModelFactory
        Method method = RequestMappingHandlerAdapter.class.getDeclaredMethod("getModelFactory", HandlerMethod.class, WebDataBinderFactory.class);
        method.setAccessible(true);
        ModelFactory modelFactory = (ModelFactory) method.invoke(handlerAdapter, handlerMethod, binderFactory);

        //初始化模型数据
        modelFactory.initModel(new ServletWebRequest(request),container,handlerMethod);


        handlerMethod.invokeAndHandle(new ServletWebRequest(request),container);

        System.out.println(container.getModel());
        context.close();
    }

    public static HandlerMethodArgumentResolverComposite getThese(AnnotationConfigApplicationContext context) {
        HandlerMethodArgumentResolverComposite composite = new HandlerMethodArgumentResolverComposite();
        composite.addResolvers(
                new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(),false),
                new PathVariableMethodArgumentResolver(),
                new RequestHeaderMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                new ServletCookieValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                new ExpressionValueMethodArgumentResolver(context.getDefaultListableBeanFactory()),
                new ServletRequestMethodArgumentResolver(),
                new ServletModelAttributeMethodProcessor(false),//必须有 @ModelAttribute
                new ServletModelAttributeMethodProcessor(true),//省略 @ModelAttribute,优先走上面的
                new RequestParamMethodArgumentResolver(context.getDefaultListableBeanFactory(), true));
        return composite;
    }
}
